package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.*;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.query.QuestionAdminPageQuery;
import com.tianji.learning.query.QuestionPageQuery;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author yang
 * @since 2024-06-25
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final InteractionReplyMapper interactionReplyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;

    /**
     * 新增问题
     *
     * @param question
     */
    @Override
    @Transactional
    public void addQuestion(QuestionFormDTO question) {
        // 获取登录用户
        Long userId = UserContext.getUser();

        //转换成po
        InteractionQuestion interactionQuestion = BeanUtils.toBean(question, InteractionQuestion.class);

        //补全属性
        interactionQuestion.setUserId(userId);

        //保存
        save(interactionQuestion);
    }

    /**
     * 分页查询问题
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> pageGetQuest(QuestionPageQuery query) {
        //1.健壮性判断
        if (query.getCourseId() == null && query.getSectionId() == null) {
            throw new BadRequestException("课程id和小节id不能都为空");
        }

        //2.根据课程id和小节id查询分页查询
        Page<InteractionQuestion> description = this.lambdaQuery()
                .select(InteractionQuestion.class, info -> !info.getProperty().equals("description"))
                .eq(query.getCourseId() != null, InteractionQuestion::getCourseId, query.getCourseId())
                .eq(query.getSectionId() != null, InteractionQuestion::getSectionId, query.getSectionId())
                .eq(query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        //3.获得提问者和回答者的id集合
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>();
        for (InteractionQuestion record : description.getRecords()) {
            if (!record.getAnonymity()) { // 只查询非匿名的问题
                userIds.add(record.getUserId());
            }
            latestAnswerIds.add(record.getLatestAnswerId());
        }

        //4.根据回答者id去获取回答者信息
        Map<Long, InteractionReply> latestAnswerMap = new HashMap();
        if (CollUtils.isNotEmpty(latestAnswerIds)) {
            List<InteractionReply> interactionReplies = interactionReplyMapper.selectBatchIds(latestAnswerIds);
            for (InteractionReply interactionReply : interactionReplies) {
                latestAnswerMap.put(interactionReply.getId(), interactionReply);
                //回答者是否要匿名处理
                if (!interactionReply.getAnonymity()) { // 匿名用户不做查询
                    userIds.add(interactionReply.getUserId());
                }
            }
        }

        //5.根据提问者id去获取提问者信息
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (CollUtils.isNotEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            for (UserDTO userDTO : userDTOS) {
                userMap.put(userDTO.getId(), userDTO);
            }
        }

        //6.封装Vo
        ArrayList<QuestionVO> questionList = new ArrayList(description.getRecords().size());

        for (InteractionQuestion r : description.getRecords()) {
            // 4.1.将PO转为VO
            QuestionVO vo = BeanUtils.copyBean(r, QuestionVO.class);
            vo.setUserId(null);
            questionList.add(vo);
            // 4.2.封装提问者信息
            if(!r.getAnonymity()){
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null) {
                    vo.setUserId(userDTO.getId());
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
            }

            // 4.3.封装最近一次回答的信息
            InteractionReply reply = latestAnswerMap.get(r.getLatestAnswerId());
            if (reply != null) {
                vo.setLatestReplyContent(reply.getContent());
                if(!reply.getAnonymity()){// 匿名用户直接忽略
                    UserDTO user = userMap.get(reply.getUserId());
                    vo.setLatestReplyUser(user.getName());
                }

            }
        }
//        for (InteractionQuestion record : description.getRecords()) {
//            QuestionVO questionVO = BeanUtils.toBean(record, QuestionVO.class);
//            questionVO.setUserName(userMap.get(record.getUserId()).getName());
//            questionVO.setUserIcon(userMap.get(record.getUserId()).getIcon());
//            questionVO.setLatestReplyContent(latestAnswerMap.get(record.getLatestAnswerId()).getContent());
//            questionVO.setLatestReplyUser(userMap.get(userMap.get(record.getLatestAnswerId()).getId()).getName());
//
//            questionList.add(questionVO);
//        }
        //7.返回结果
        return PageDTO.of(description, questionList);

    }

    /**
     * 根据id查询问题
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO getQuestionById(Long id) {
        InteractionQuestion question = getById(id);
        if (question == null || question.getHidden()) {
            // 没有数据或者是被隐藏了
            return null;
        }

        // 3.查询提问者信息
        UserDTO user = null;
        if (!question.getAnonymity()) {
            user = userClient.queryUserById(question.getUserId());
        }
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);

        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        return vo;
    }

    /**
     * 管理端分页查询问题
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> gitAdminQuestionPage(QuestionAdminPageQuery query) {

        // 1、调用ES处理课程名称，得到课程ID集合
        List<Long> courseIds = null;
        if (ObjectUtil.isNotEmpty(query.getCourseName())) {
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if(ObjectUtil.isEmpty(courseIds)){
                return PageDTO.empty(0L,0L);
            }
        }
        //2.根据参数进行分页查询
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(ObjectUtil.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtil.isNotEmpty(query.getStatus()), InteractionQuestion::getStatus, query.getStatus())
                .ge(ObjectUtil.isNotEmpty(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime())
                .le(ObjectUtil.isNotEmpty(query.getEndTime()),  InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        if(ObjectUtil.isEmpty(page.getRecords())){
            return PageDTO.empty(page);
        }
        //3.收集id
        Set<Long> cataIds = new HashSet<>();
        Set<Long> cIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        for (InteractionQuestion record : page.getRecords()) {
            cataIds.add(record.getSectionId());
            cataIds.add(record.getChapterId());
            cIds.add(record.getCourseId());
            userIds.add(record.getUserId());
        }

        //4.根据id查询用户
        Map<Long, UserDTO> userMap = new HashMap<>();
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        for (UserDTO userDTO : userDTOS) {
            userMap.put(userDTO.getId(), userDTO);
        }

        //5.查找id查找课程信息
        Map<Long, CourseSimpleInfoDTO> questionMap = new HashMap<>();
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(cIds);
        for (CourseSimpleInfoDTO record : simpleInfoList) {
            questionMap.put(record.getId(), record);
        }

        //6.根据id查找章信息
        Map<Long, CataSimpleInfoDTO> chapterMap = new HashMap<>();
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(cataIds);
        for (CataSimpleInfoDTO cataSimpleInfoDTO : cataSimpleInfoDTOS) {
            chapterMap.put(cataSimpleInfoDTO.getId(), cataSimpleInfoDTO);
        }

        //7.封装数据
        List<QuestionAdminVO> adminList = new ArrayList<>();
        for (InteractionQuestion oldRecord : page.getRecords()) {
            QuestionAdminVO record = BeanUtils.toBean(oldRecord, QuestionAdminVO.class);

            //7.1获取三级分类和课程名字
                CourseSimpleInfoDTO courseSimpleInfoDTO = questionMap.get(oldRecord.getCourseId());
                List<Long> categoryIds = courseSimpleInfoDTO.getCategoryIds();
                String categoryNames = categoryCache.getCategoryNames(categoryIds);

            //7.2封装信息
                record.setCategoryName(categoryNames);
                record.setCourseName(courseSimpleInfoDTO.getName());

                record.setUserName(userMap.get(oldRecord.getUserId()).getName());
                record.setChapterName(chapterMap.get(oldRecord.getChapterId()).getName());
                record.setSectionName(chapterMap.get(oldRecord.getSectionId()).getName());

            //7.3添加到集合中
                adminList.add(record);
        }

        //8.返回结果
        return PageDTO.of(page, adminList);
    }

    /**
     * 修改问题
     *
     * @param question
     * @param id
     */
    @Override
    public void updateQuestion(QuestionFormDTO question, Long id) {
        //1.健壮性判断
        if(id == null){
            throw new BadRequestException("id不能为空");
        }

        if (question.getTitle()==null){
            throw new BadRequestException("标题不能为空");
        }

        //2.判断问题是否是当前用户提出的
        Long user = UserContext.getUser();
        InteractionQuestion one = this.lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .one();
        if (one.getUserId()!=user){
            throw new BadRequestException("只能修改自己的问题");
        }

        //3.修改问题
        this.lambdaUpdate()
                .eq(InteractionQuestion::getId,id)
                .set(InteractionQuestion::getTitle,question.getTitle())
                .set(InteractionQuestion::getDescription,question.getDescription())
                .set(InteractionQuestion::getAnonymity,question.getAnonymity()).update();
    }

    /**
     * 删除问题
     *
     * @param id
     */
    @Override
    @Transactional
    public void deleteQuestion(Long id) {
        //1.健壮性判断
        if(id == null){
            throw new BadRequestException("id不能为空");
        }
        //2.判断问题是否是当前用户提出的
        Long user = UserContext.getUser();
        InteractionQuestion one = this.lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .one();
        if (one.getUserId()!=user){
            throw new BadRequestException("只能删除自己的问题");
        }
        //3.删除问题
        this.removeById(id);

        //4.删除回答和评论
        interactionReplyMapper.delete( new LambdaQueryWrapper<InteractionReply>().eq(InteractionReply::getQuestionId,id));
    }

    /**
     * 修改问题隐藏状态
     *
     * @param id
     * @param hidden
     */
    @Override
    public void updateQuestionHidden(Long id, Boolean hidden) {
        //1.健壮性判断
        if(id == null){
            throw new BadRequestException("id不能为空");
        }
        if (hidden == null){
            throw new BadRequestException("隐藏状态不能为空");
        }

        this.lambdaUpdate()
                .eq(InteractionQuestion::getId,id)
                .set(InteractionQuestion::getHidden,hidden)
                .update();
    }

    /**
     * 管理端查询问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO getAdminQuestionById(Long id) {
        //1.健壮性判断
        if (id == null){
            throw new BadRequestException("id不能为空");
        }

        //2.查询问题信息
        InteractionQuestion one = this.lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .one();

        //3.根据提问者id去获取信息
        Long userId = one.getUserId();
        UserDTO userDTO = userClient.queryUserById(userId);

        if (userDTO == null){
            throw new BadRequestException("用户不存在");
        }

        //4.根据课程id查询课程三级分类和课程名称
        Long courseId = one.getCourseId();
        CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(courseId, false, true);
        if (courseInfoById == null){
            throw new BadRequestException("课程不存在");
        }
        List<Long> categoryIds = courseInfoById.getCategoryIds();
        String categoryNames = categoryCache.getCategoryNames(categoryIds);

        List<CatalogueDTO> chapters = courseInfoById.getChapters();

        //5.获取老师信息
        List<Long> teacherIds = courseInfoById.getTeacherIds();
        List<UserDTO> userDTOS1 = userClient.queryUserByIds(teacherIds);
        List<String> teacherNames =new ArrayList<>();
        for (UserDTO dto : userDTOS1) {
            teacherNames.add(dto.getName());
        }
        String join = StrUtil.join("/", teacherNames);

        //6.根据章节id查询章节名称
        Long chapterId = one.getChapterId();
        Long sectionId = one.getSectionId();
        List<Long> chapterIds = new ArrayList<>();
        chapterIds.add(chapterId);
        chapterIds.add(sectionId);
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(chapterIds);
        Map<Long, CataSimpleInfoDTO> chapterMap = new HashMap<>();
        for (CataSimpleInfoDTO cataSimpleInfoDTO : cataSimpleInfoDTOS) {
            chapterMap.put(cataSimpleInfoDTO.getId(),cataSimpleInfoDTO);
        }
        //7.封装数据

            //封装提问者数据
            QuestionAdminVO record = BeanUtils.toBean(one, QuestionAdminVO.class);
            record.setUserName(userDTO.getName());
            record.setUserIcon(userDTO.getIcon());
            //封装三级分类和课程名称
            record.setCategoryName(categoryNames);
            record.setCourseName(courseInfoById.getName());
            //封装老师名称
            record.setTeacherName(join);
            //封装章节名称
            record.setChapterName(chapterMap.get(chapterId).getName());
            record.setSectionName(chapterMap.get(sectionId).getName());
            //修改状态
            record.setStatus(QuestionStatus.CHECKED);

        return record;
    }


}
